package com.tourism.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tourism.admin.common.Result;
import com.tourism.admin.controller.BaseController;
import com.tourism.admin.model.dto.UserAddressDto;
import com.tourism.admin.model.entity.Permission;
import com.tourism.admin.model.entity.RolePermission;
import com.tourism.admin.model.entity.User;
import com.tourism.admin.model.entity.UserRole;
import com.tourism.admin.enums.PwdEnum;
import com.tourism.admin.enums.RoleEnum;
import com.tourism.admin.mapper.UserMapper;
import com.tourism.admin.service.PermissionService;
import com.tourism.admin.service.RoleService;
import com.tourism.admin.service.UserRoleService;
import com.tourism.admin.service.UserService;
import com.tourism.admin.utils.TokenUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder; //注入bcryct加密

    @Autowired
    private UserService userService;

    @Autowired
    private UserRoleService userRoleService;

    @Autowired
    private RoleService roleService;

    @Autowired
    private PermissionService permissionService;


    @Override
    public Page<User> findPage(Page<User> page, String nickName) {
        return this.baseMapper.findPage(page,nickName);
    }

    @Override
    public List<UserAddressDto> countAddress() {
        return this.baseMapper.countAddress();
    }

    @Override
    public User selectByName(String username) {
        return this.baseMapper.selectByName(username);
    }

    @Override
    public int updatePass(Map<String, Object> map) {
        return updatePass(map);
    }


                //登录认证
    public Result<?> login(User user) {
        User userPwd = userService.selectByName(user.getUsername());
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username", user.getUsername());
        queryWrapper.eq("password", userPwd.getPassword());
        User res = userService.getOne(queryWrapper);

        // 判断密码是否正确
        if (!bCryptPasswordEncoder.matches(user.getPassword(), userPwd.getPassword())) {
            return Result.error("-1","密码错误");
        }
        if (res == null) {
            return Result.error("-1","用户名或密码错误");
        }
        HashSet<Permission> permissionSet = new HashSet<>();
        // 1. 从user_role表通过用户id查询所有的角色信息
        Integer userId = res.getId();
        List<UserRole> userRoles = roleService.getUserRoleByUserId(userId);
        // 设置角色id
        res.setRoles(userRoles.stream().map(UserRole::getRoleId).distinct().collect(Collectors.toList()));
        for (UserRole userRole : userRoles) {
            // 2.根据roleId从role_permission表查询出所有的permissionId
            List<RolePermission> rolePermissions = permissionService.getRolePermissionByRoleId(userRole.getRoleId());
            for (RolePermission rolePermission : rolePermissions) {
                Integer permissionId = rolePermission.getPermissionId();
                // 3. 根据permissionId查询permission信息
                Permission permission = permissionService.getById(permissionId);
                permissionSet.add(permission);
            }
        }
        // 对资源根据id进行排序
        LinkedHashSet<Permission> sortedSet = permissionSet.stream().sorted(Comparator.comparing(Permission::getId)).collect(Collectors.toCollection(LinkedHashSet::new));
        //设置当前用户的资源信息
        res.setPermissions(sortedSet);

        // 生成token
        String token = TokenUtils.genToken(res);
        res.setToken(token);

        return Result.success().setData(res);
    }

    public Result<?> register(User user) {
        User res = userService.getOne(Wrappers.<User>lambdaQuery().eq(User::getUsername, user.getUsername()));
        if (res != null) {
            return Result.error("-1","用户名重复");
        }
//        if (user.getPassword() == null) {
//            user.setPassword("123456");
//        }
        User userInfo = User.builder()
                .username(user.getUsername())
                .password(bCryptPasswordEncoder.encode(user.getPassword()))
                .nickName("用户" + IdWorker.getId())
                .build();

        userService.save(userInfo);

        UserRole userRole = UserRole.builder()
                .userId(userInfo.getId())
                .roleId(RoleEnum.USER.getRoleId())
                .build();
        userRoleService.save(userRole);
        return Result.success();
    }


    public Result<?> saves(User user) {
        if (user.getPassword() == null) {
            user.setPassword(bCryptPasswordEncoder.encode(PwdEnum.PASSWORD.getPassword()));
        }
        userService.save(user);

        UserRole userRole = UserRole.builder()
                .userId(user.getId())
                .roleId(RoleEnum.USER.getRoleId())
                .build();
        userRoleService.save(userRole);

        return Result.success();
    }


    public Result<?> pass(Map<String, Object> map) {
        User user = userService.getById((Integer) map.get("userId"));
        if (user== null) {
            return Result.error("-1","未找到用户");
        }
        if (!bCryptPasswordEncoder.matches(map.get("password").toString(), user.getPassword())) {
            return Result.error("-1","密码错误");
        }
        map.put("newPass", (bCryptPasswordEncoder.encode(map.get("newPass").toString())));
        userService.updatePass(map);
        return Result.success();
    }

    public Result<?> changeRole(User user) {
        // 先根据角色id删除所有的角色跟权限的绑定关系
        roleService.deleteRoleByUserId(user.getId());
        // 再新增 新的绑定关系
        for (Integer roleId : user.getRoles()) {
            roleService.insertUserRole(user.getId(), roleId);
        }

        // 获取当前登录用户的角色id列表
        BaseController baseController = new BaseController();
        User currentUser = baseController.getUser();
        // 如果当前登录用户的角色列表包含需要修改的角色id，那么就重新登录
        if (user.getId().equals(currentUser.getId())) {
            return Result.success();
        }
//        如果不包含，则返回false，不需要重新登录。
        return Result.success();
    }

}
